// Include header
#include "character.h"

// Include misc
#include "misc_functions.h"

Character::Character(CharacterType type, u32 x, u32 y, s16 direction, GameEngine* gameEngine)
{
	// Set type
	this->type=type;

	// Set position
	this->x=x;
	this->y=y;

	// Set direction
	this->direction=direction;

	// Set game engine
	this->gameEngine=gameEngine;

	// Set status
		onGround=false;

	// Clear action flags
	actions=0;
}

void Character::iterate()
{
	// Update status
	if (gameEngine_checkCollision(gameEngine, x, y+1, &boundingBox, COLLISION_TERRAIN))
	{
		onGround=true;
		jumpTime=C_JUMP_TIME;
	}
	else
	{
		onGround=false;
	}

	// Gravity
	if (onGround)
	{
		if (ySpeed>0)
		{
			ySpeed=0;
		}
	}
	else
	{
		if (ySpeed<C_MAX_FALL_SPEED)
		{
			ySpeed+=C_GRAVITY;
		}
	}

	// Update position by speed
		// X
		if ((xSpeed!=0)&&(gameEngine_checkCollision(gameEngine, x+xSpeed, y, &boundingBox, COLLISION_TERRAIN)))
		{
			u16 offset=1;
			s16 sign=misc_sign(xSpeed);
			while (gameEngine_checkCollision(gameEngine, x+xSpeed-offset*sign, y, &boundingBox, COLLISION_TERRAIN))
			{
				if (offset*sign==xSpeed)
				{
					break;
				}
				offset++;
			}
			x+=(s32) xSpeed-offset*sign;
		}
		else
		{
			x+=(s32) xSpeed;
		}

		// Y
		if ((ySpeed!=0)&&(gameEngine_checkCollision(gameEngine, x, y+ySpeed, &boundingBox, COLLISION_TERRAIN)))
		{
			u16 offset=1;
			s16 sign=misc_sign(ySpeed);
			while (gameEngine_checkCollision(gameEngine, x, y+ySpeed-offset*sign, &boundingBox, COLLISION_TERRAIN))
			{
				if (offset*sign==ySpeed)
				{
					break;
				}
				offset++;
			}
			y+=(s32) ySpeed-offset*sign;
		}
		else
		{
			if (ySpeed!=0)
			{
				y+=(s32) ySpeed;
			}
		}

	// Do actions
		// Move right
		if (actions&C_ACTION_RIGHT)
		{
			direction=1;
			if (!gameEngine_checkCollision(gameEngine, x+C_WALK_SPEED, y, &boundingBox, COLLISION_TERRAIN))
			{
				x+=C_WALK_SPEED;
			}
		}

		// Move left
		if (actions&C_ACTION_LEFT)
		{
			direction=-1;
			if (!gameEngine_checkCollision(gameEngine, x-1, y, &boundingBox, COLLISION_TERRAIN))
			{
				x-=C_WALK_SPEED;
			}
		}

		// Jump
		if (actions&C_ACTION_JUMP)
		{
			if (jumpTime>0)
			{
				ySpeed=-C_JUMP_SPEED;
				jumpTime--;
			}
		}
		else
		{
			jumpTime=0;
		}

		// Hijack slide action and float instead
		if (actions&C_ACTION_SLIDE)
		{
			y-=24;
		}

		// Clear action flags
		actions=0;
}

void Character::setActions(u32 actions)
{
	this->actions|=actions;
}
